﻿using System;
using Localization;
using SinBiota.Model.Business.AuthenticationServices.Interfaces;
using SinBiota.Model.Business.PersistenceServices.Interfaces;
using SinBiota.Model.Entities;

namespace SinBiota.Model.Business.AuthenticationServices.Implementation
{
    public class PermissionServices : IPermissionServices
    {
        private readonly IUserPersistenceServices _userPersistence;
        private readonly IProjectPersistenceServices _projectPersistenceServices;

        public PermissionServices(IUserPersistenceServices userPersistence, IProjectPersistenceServices projectPersistenceServices)
        {
            _userPersistence = userPersistence;
            _projectPersistenceServices = projectPersistenceServices;
        }

        public bool IsAdmin(string username)
        {
            var user = _userPersistence.FindByUsername(username);
            return user != null && user.Role.Equals(Role.Admin);
        }

        public bool CanEditUser(string username, User userBeingEdited)
        {
            var user = _userPersistence.FindByUsername(username);
            // Admin, own user or coordinator can edit:
            return user.Role.Equals(Role.Admin) || user.Equals(userBeingEdited) || (user.IsCoordinatorOfUser(userBeingEdited) && !userBeingEdited.Role.Equals(Role.Admin));
        }

        public bool CanDisplayUserDetails(string username, User userBeingEdited)
        {
            var user = _userPersistence.FindByUsername(username);
            // Admin, own user or coordinator can display:
            return user.Role.Equals(Role.Admin) || user.Equals(userBeingEdited) || user.IsCoordinatorOfUser(userBeingEdited);
        }

        public bool CanEditOccurrence(string username, Occurrence occurrence)
        {
            return CanEditOccurrence(_userPersistence.FindByUsername(username), occurrence);
            
        }

        public bool CanEditOccurrence(User user, Occurrence occurrence)
        {
            return user != null && (user.Role.Equals(Role.Admin) || user.Equals(occurrence.User) || user.CoordinatorProjects.Contains(occurrence.Project));
        }


        public bool CanCopyOccurrence(string username, Occurrence occurrence)
        {
            var user = _userPersistence.FindByUsername(username);
            return user != null && 
                ((user.Role.Equals(Role.Admin) || user.Equals(occurrence.User)) || user.MemberProjects.Contains(occurrence.Project) || user.CoordinatorProjects.Contains(occurrence.Project));
        }

        public bool CanDeleteOccurrence(string username, Occurrence occurrence)
        {
            var user = _userPersistence.FindByUsername(username);
            return user != null &&
                ((user.Role.Equals(Role.Admin) || user.Equals(occurrence.User)) || user.CoordinatorProjects.Contains(occurrence.Project));
        }

        public bool CanManageProject(string username, int projectId)
        {
            var user = _userPersistence.FindByUsername(username);
            if (user.Role.Equals(Role.Admin)) return true;
            var project = _projectPersistenceServices.FindById(projectId);
            return user.CoordinatorProjects.Contains(project);
        }

        public bool CanViewUserList(string username)
        {
            var user = _userPersistence.FindByUsername(username);
            return user.Role.Equals(Role.Admin) || user.IsCoordinator();
        }

        public bool CanCreateUser(string username)
        {
            var user = _userPersistence.FindByUsername(username);
            return user.Role.Equals(Role.Admin) || user.IsCoordinator();
        }

        public bool CanEditProject(string username, Project project)
        {
            var user = _userPersistence.FindByUsername(username);
            return user.Role.Equals(Role.Admin) || project.Coordinators.Contains(user);
        }

        public bool CanAddTaxonChildren(string username, Taxon taxon)
        {
            var user = _userPersistence.FindByUsername(username);
            return user != null && (taxon.Rank.EndsWith(COLRank.Genus) || taxon.Rank.EndsWith(COLRank.Family) || taxon.Rank.EndsWith(COLRank.Order) || taxon.Rank.EndsWith(COLRank.Species));
        }

        public bool CanIncludeOccurrence(string username, Project project)
        {
            var user = _userPersistence.FindByUsername(username);
            return user != null && (user.Role.Equals(Role.Admin) || user.CoordinatorProjects.Contains(project) || user.MemberProjects.Contains(project));
            
        }

        public bool CanAddProjectMember(int projectId, string username)
        {
            var user = _userPersistence.FindByUsername(username);
            var project = _projectPersistenceServices.FindById(projectId);
            return CanAddProjectMember(project, user);
        }
        public bool CanAddProjectMember(Project project, User user)
        {
            return (user != null && project != null && ((user.Role.Equals(Role.Admin)) || user.CoordinatorProjects.Contains(project)));
        }

        public bool CanAddProjectCoordinator(Project project, User user)
        {
            return (user != null && project != null && ((user.Role.Equals(Role.Admin)) || user.CoordinatorProjects.Contains(project)));
        }


    }
}